XJTUSE - 数电实验
基于自拟协议的通信装置
1.任务探讨
1.1 信息传输
随着计算机技术和电子信息技术的发展,信息的传输效率,传输安全性和传输准 确率变得越来越重要,人们为了适应不同的通信场景创建了多种多样的通信协议以满 足不同实际需求。
1.1.1 BCD码
BCD 码(Binary-Coded Decimal),用 4 位二进制数来表示 1 位十进制中的 0∼9 这 10 个数码,是一种二进制的数字编码形式。BCD 码是十位二进制码, 也就是将十进制 的数字转化为二进制, 但是和普通的转化有一点不同, 每一个十进制的数字 0-9 都对应 着一个四位的二进制码图 1-1 表示 BCD 码编译的 1∼9 数字的示意图

1.1.2 奇偶校验码
校验码的出现是为了保障传输信息准确无误,常见的单位校验码有奇校验码,偶 校验码。其中奇校验:原始码流 + 校验位总共有奇数个数字“1”。偶校验:原始码流 + 校验位总共有偶数个数字“1”。通常把校验码放在码流的前面或者后面。如图 1-2 所示

1.2 实验目的
了解到了信息传输的种种原理和现况,我们小组决定通过 procise 编程软件和 FMK50T4 制作简易的基于通信协议的信息传输装置。
1.2.1 传输信息的方式
为了直观显示,实时输入信号,我们决定采用 FMK50T4 板上的按钮进行数据输入, 为了传输数据,共使用了两个按钮为 SW4 和 SW7。
1.2.2 传输信息协议
我们自拟了一套简易的传输协议,具体可以查看图 2-2状态机。
下面进行简要说明。

协议说明:先输入 0,然后状态机才进入 start 状态,才可以进行信息传输。然后, 接受四位 BCD 码,再输入 1,状态机进入 stop 状态,一次通信完成。若不按照此协议, 无法完成通信。
1.2.3 信息显示方式
为了表示传输的信息,我们决定采用 FMK50T4 板上的 led 等进行数据显示,led 对 应数据名称如表 1-2下:
下面讲解参数 done 和 verify 含义:
done 表示为一次传输协议是否成功。
verify 为根据 4 为 BCD 码生成的奇校验码。

1.2.4 其他模块
为了尽可能模拟信息传递的现实因素过程以及体现状态机的作用,我们设计了其 它按钮代表了不同功能。如表 1-3下:

2 PROCISE实现
2.1 功能实现
总设计电路电子图如下:

2.1.1信息传输
btn 按钮为录入 01 数据按钮,switch 按钮为切换 01 数据按钮录入数据核心 Verilog 代码块如下:
always@(posedge btn) begin if (!reset) mem <= 1; else mem <= mem*step + (data_in?); end
Verilog 代码说明:当按下 btn 按钮后,会存储数据 mem 会进行更新,这利用了二进制 乘 2 进位的性质。比如最开始 mem 为 4 ′ b0001; 我录入数据 1,有 mem = mem∗step+1, 则 4 ′ b0011, 反之录入数据 0,有 mem = mem ∗ step,则 4 ′ b0010 改变传输核心 Verilog 代码块如下:
always@(posedge switch)begin data_in <= ~data_in; end
Verilog代码说明:当按下switch按钮后,
2.1.2 状态转移
状态机状态如 2-1表所示

状态转移图如图 2-2所示

需要说明的是,虽然状态转移图不是最简的状态图,但是为了解决实际传输数据 遇到的问题,该状态图没有必要进行化简。
该有限状态机的状态表展示如下:

Verilog 核心代码如下:
always@(posedge btn) begin nstate=idle; case(state) idle: nstate=data_in?idle:start; start: nstate=data; data: nstate=(cnt==4)?(data_in?stop:error):data; error: nstate=data_in?idle:error; stop: nstate=stop; default:nstate=idle; endcase end
上述代码为状态转移代码,使用了 case 语句进行状态判断和状态转移。
2.1.3 参数实现
我们有两个重要参数,一个是 done 参数,表示传输完毕。一个是 verify,表示奇校验码。
当完成一次协议传输后,即进入状态 stop 时,done 表现为 1,其余状态均表现为 0;当完成一次协议传输后,按照协议对数据进行校验,若满足协议规则,verify 表示 为 1,否则为 0。Verilog 核心代码如下:
always@(posedge change)begin if(!reset)begin done<=0; cnt<=0; end else case(nstate) ... stop: begin done<=1; cnt<=0; end ... endcase end
上述为参数 done 赋值模块,其中”...” 为省略的代码。
我们采用实时更新 verify 的方式,Verilog 代码如下:
assign verify = !(led[1]^led[2]^led[3]^led[4]);
当 4 位 BCD 码存在奇数个 1 时,verify 为 0;当 4 位 BCD 码存在偶数个 1 时,verify 为 1;
2.2 仿真波形图
2.2.1 输入波形仿真图
- 输入的情况

可以看到,当按下 btn 键后,led 从“6’b000001”变到了”6’b000011”,表明确实输 出了 1。
- 转化 01 的情况

可以看到,当按下 switch,进行转化后,再按下 btn 键后,led 从“6’b000001”变 到了”6’b000010”,表明确实进行了转换并且输出了 0。而后面再次按下 switch 按钮后, 也成功进行了转换。
2.2.2 参数波形仿真图
done

当输入满足通讯协议时,参数 done 从 0 转化为 1,表明通信正常运行。
verify

可以看到 verify 波形图实时根据 4 位 BCD 码进行改变。
2.3 约束文件
波形仿真图成功运行也并不代表在硬件上可以运行,在硬件上运行需要一定的约 束文件进行约束,因此需要配置约束文件。
2.3.1 UCF 约束文件
NET "done" LOC = M17; NET "led[0]" LOC = N17; NET "led[1]" LOC = P18; NET "led[2]" LOC = P19; NET "led[3]" LOC = N19; NET "led[4]" LOC = N18; NET "led[5]" LOC = R18; NET "verify" LOC = R19; NET "btn" LOC = AA22; NET "switch" LOC = T20; NET "reset" LOC = U20; NET "change" LOC = T19;
2.3.2 FDC 约束文件
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets "btn"]; set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets "switch"]; set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets "change"];
下面阐述设置 FDC 文件的约束文件原因,工具在编译时通常会自动识别设计中 的时钟网络,并将其分配到专用的时钟布局布线资源中。通过对某些时钟网络设置 CLOCK_DEDICAT ED_ROUT E 值为 FALSE,可以将被识别为时钟网络并按照时 钟网络进行布局布线的时钟信号安排到通用的布线资源中。比如,某些时钟信号由于 设计疏忽或其它原因,没有被安排到电子器件的时钟专用引脚上,在编译的时候就会 报错,此时就可以使用 CLOCK_DEDICAT ED_ROUT E 约束来忽略这个错误。
3 实验环节
3.1 数据录入
不同测试图片如下:

可以看到 led 灯 D7 − D12 有着不同闪烁排序,这是我通过 btn 和 switch 按钮录入 不同的 01 数据,从而使 led 灯呈现不同的状态。这表明数据录入成功!
3.2 参数测试
3.2.1 参数 done
测试图片如下:

按照协议进行信息传输后,状态机进入 stop 状态后,done 参数从 0 变为 1,则对 应的 led 灯 D6 从亮变为暗,协议成立并且状态机正常工作,信息传输成功。但是,当 没有按照协议进行信息传输时候,状态机不会进入 stop 状态,对应的 led 灯 D6 一直保 持亮着,信息传输失败。
3.2.2 参数 verify
测试图片如下

可以看到 verify 对应的 led 灯的明暗确实是按照 4 位 BCD 码变化的,而且满足奇 校验码的要求。
3.3 reset 测试
reset 按钮测试如下:

可以看到当按下 reset 按钮后,恢复到初始状态了。
附录
Verilog 代码
timescale 1ns / 1ps `module top_module( input btn, input switch, input reset, input change, output reg done, output [] led, output verify ); parameter idle=0,start=1,data=2,stop=3,error=4; reg [] state,nstate; reg data_in = 1; reg [] cnt; reg [] mem = 1; reg [] step = 4'b0010; always@(posedge btn) begin if (!reset) mem <= 1; else mem <= mem*step + (data_in?); end
always@(posedge change) begin
if(!reset)
state <= idle;
else
state <= nstate;
end
always@(posedge switch)begin
data_in <= ~data_in;
end
// 状态转移代码块
always@(posedge btn) begin
nstate=idle;
case(state)
idle: nstate=data_in?idle:start;
start: nstate=data;
data: nstate=(cnt==4)?(data_in?stop:error):data;
error: nstate=data_in?idle:error;
stop: nstate=stop;
default:nstate=idle;
endcase
end
// 输出表
always@(posedge change)begin
if(!reset)begin
done<=0;
cnt<=0;
end
else
case(nstate)
data: begin
done<=0;
cnt<=cnt+1'b1;
end
stop: begin
done<=1;
cnt<=0;
end
default: begin
done<=0;
cnt<=0;
end
endcase
end
assign led = mem;
assign verify = (mem[1]^mem[2]^mem[3]^mem[4])
endmodule`
UCF 代码
NET "done" LOC = M17; NET "led[0]" LOC = N17; NET "led[1]" LOC = P18; NET "led[2]" LOC = P19; NET "led[3]" LOC = N19; NET "led[4]" LOC = N18; NET "led[5]" LOC = R18; NET "verify" LOC = R19; NET "btn" LOC = AA22; NET "switch" LOC = T20; NET "reset" LOC = U20; NET "change" LOC = T19;
FDC代码
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets "btn"]; set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets "switch"]; set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets "change"];